#include <thread.h>

extern struct thread *current_thread;

/* 线程定时器超时执行函数 */
static void thread_timeout(void *args)
{
	register ubase_t level;
	struct thread *thread = (struct thread *)args;
	
	assert(thread != NULL);
	
	level = interrupt_disable();
	
	schedule_add(thread);
	
	interrupt_enable(level);
	
	schedule();
}

/* 线程退出后的清理工作 */
static void thread_exit(void)
{
	struct thread *thread;
	register base_t level;

	/* 获取当前线程 */
	thread = thread_self();

	/* 将线程标记为销毁状态 */
	thread->status |= THREAD_DESTROY;

	level = interrupt_disable();

	/* 从调度器中移除 */
	schedule_remove(thread);

	/* 从object列表中移除 */
	object_deinit(&thread->parent);

	/* 立即调度下一个线程 */
	schedule();

	/* 如果是动态申请的线程，回收线程占用的空间 */
	if (thread->flag & THREAD_FLAG_DYNAMIC)
	{
		free(thread->stack_addr);
		free(thread);
	}

	interrupt_enable(level);
}

static void __thread_init(struct thread *thread,
			const char *name,
			void (*entry)(void *),
			void *parameter,
			base_t stack_size,
			uint8_t priority)
{
	thread->entry = entry;
	thread->parameter = parameter;
	thread->init_tick = 10;
	thread->remaining_tick = thread->init_tick;
	thread->stack_size = stack_size;

	thread->status = THREAD_SUSPEND;

	assert(priority < THREAD_MAX_PRIORITY);
	thread->priority = priority;
	thread->mask_priority = BIT(priority);

	timer_init(&thread->timer, name, thread_timeout, thread, 0, TIMER_FLAG_SINGLE);

	thread->parent.type = CLASS_TYPE_THREAD;
	object_init(&thread->parent, name);
}

/* 初始化线程 */
err_t thread_init(struct thread *thread,
			const char *name,
			void (*entry)(void *),
			void *parameter,
			base_t stack_size,
			uint8_t *stack,
			uint8_t priority)
{
	if (thread == NULL || stack == NULL)
		return -EINVAL;

	thread->stack_addr = stack;
	thread->sp = stack_init(entry,
				parameter,
				(uint8_t *)thread->stack_addr + stack_size,
				thread_exit);

	thread->flag = THREAD_FLAG_STATIC;

	__thread_init(thread,
				  name,
				  entry,
				  parameter,
				  stack_size,
				  priority);
	return 0;
}

/* 创建线程 */
struct thread *thread_creat(const char *name,
			void (*entry)(void *),
			void *parameter,
			base_t stack_size,
			uint8_t priority)
{
	struct thread *thread = (struct thread *)malloc(sizeof(struct thread));

	if (thread == NULL)
		return NULL;

	thread->stack_addr = (uint8_t *)malloc(stack_size);
	if (thread->stack_addr == NULL)
		return NULL;

	thread->sp = stack_init(entry,
				parameter,
				(uint8_t *)thread->stack_addr + stack_size,
				thread_exit);

	thread->flag = THREAD_FLAG_DYNAMIC;
	
	__thread_init(thread,
				  name,
				  entry,
				  parameter,
				  stack_size,
				  priority);

	return thread;
}

/* 将线程加入到就绪队列 */
err_t thread_resume(struct thread *thread)
{
	base_t level;

	/* 如果当前线程不是挂起状态，则返回错误代码 */
	if ((thread->status & THREAD_SUSPEND) == 0)
		return -EAGAIN;

	level = interrupt_disable();

	/* 将当前线程加入到就绪队列中 */
	schedule_add(thread);

	interrupt_enable(level);

	return 0;
}

/* 将线程挂起 */
err_t thread_suspend(struct thread *thread)
{
	base_t level;

	level = interrupt_disable();

	schedule_remove(thread);

	interrupt_enable(level);

	return 0;
}

/* 启动线程 */
err_t thread_start(struct thread *thread)
{
	return thread_resume(thread);
}

/* 线程休眠函数 */
err_t thread_sleep(ubase_t tick)
{
	base_t level;
	err_t ret = 0;
	struct thread *thread = thread_self();

	level = interrupt_disable();

	thread_suspend(thread);

	ret = timer_control(&thread->timer, TIMER_CMD_SET_TIME, &tick);
	if (ret < 0)
		goto __exit;

	ret = timer_start(&thread->timer);
	if (ret < 0)
		goto __exit;

	interrupt_enable(level);

	schedule();

__exit:
	interrupt_enable(level);

	return ret;
}

struct thread *thread_find(const char *name)
{
	return (struct thread *)object_find(name, CLASS_TYPE_THREAD);
}

struct thread *thread_self(void)
{
	return current_thread;
}
